package cn.abcsys.cloud.devops.monitor.core.impl;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

import cn.abcsys.cloud.devops.monitor.common.HttpClient;
import cn.abcsys.cloud.devops.monitor.common.SystemConfig;
import cn.abcsys.cloud.devops.monitor.constant.Common;
import cn.abcsys.cloud.devops.monitor.constant.ZabbixBean;
import cn.abcsys.cloud.devops.monitor.core.MonitorCore;
import cn.abcsys.cloud.devops.monitor.utils.Result;
/**
 * @author mayunhao
 *
 */
@Service("monitorCore")
@Scope("prototype")
public class MonitorCoreImpl implements MonitorCore {
	private static final Logger LOGGER = Logger.getLogger(MonitorCoreImpl.class);
	@Autowired
	private HttpClient httpClient;
	private String zabbixApiUrl;
	@Autowired
	private SystemConfig systemConfig;
	@Override
	public Result hostMonitor(JSONObject paramIn){
		String monitorType = paramIn.getString("monitorType");
		Result result = this.checkParam(paramIn);
		if(!result.isSuccess()){
			return result;
		}
		this.assembleUrl();
		JSONObject param = new JSONObject();
		param.put("id", String.valueOf(System.currentTimeMillis()));
		JSONObject auth = this.zabbixAuth(param);
		if(null==auth){
			LOGGER.error("获取认证令牌失败");
			return new Result(false,
					"获取认证令牌失败");
		}
		param.put("auth", auth.get("result"));
		param.put("objectName",paramIn.get("objectName"));
		JSONObject monitorHost = this.zabbixGetHost(param);
		if(null==monitorHost){
			LOGGER.error("查询监控对象["+paramIn.get("objectName")+"]失败");
			return new Result(false,
					"查询监控对象["+paramIn.get("objectName")+"]失败");
		}
		if(monitorHost.getJSONArray("result").isEmpty()){
			LOGGER.info("查询监控对象["+paramIn.get("objectName")+"]结果为空");
			return new Result(true,"", "Result is empty.");
		}
		param.put("hostid", monitorHost.getJSONArray("result").getJSONObject(0).get("hostid"));
		JSONObject monitorItem = this.zabbixGetItem(param);
		if(null==monitorItem){
			LOGGER.error("查询监控对象["+paramIn.get("objectName")+"]监控项["+paramIn.get("monitorItem")+"]失败");
			return new Result(false,
					"查询监控对象["+paramIn.get("objectName")+"]监控项["+paramIn.get("monitorItem")+"]失败");
		}
		param.put("time_from", paramIn.getLong("time_from"));
		param.put("time_till", paramIn.getLong("time_till"));
		JSONArray items = monitorItem.getJSONArray("result");
		JSONObject resultObject = new JSONObject();
		for(int i=0;i<items.size();i++){
			JSONObject jsonObject = items.getJSONObject(i);
			if(monitorType.endsWith("host")){
				//CPU
				if(Common.HOST_CPU.equals(jsonObject.getString("key_"))){
					JSONArray itemArray = new JSONArray();
					itemArray.add(jsonObject.get("itemid"));
					param.put("itemids",itemArray);
					param.put("history",0);
					JSONObject monitorJsonObject = zabbixGetMonitorData(param);
					resultObject.put("cpu", monitorJsonObject.getJSONArray("result"));
				}
				//mem
				if(Common.HOST_MEM_AVAILABLE.equals(jsonObject.getString("key_"))){
					JSONArray itemArray = new JSONArray();
					itemArray.add(jsonObject.get("itemid"));
					param.put("itemids",itemArray);
					param.put("history",3);
					JSONObject monitorJsonObject = zabbixGetMonitorData(param);
					resultObject.put("mem_available", monitorJsonObject.getJSONArray("result"));
				}
				//mem
				if(Common.HOST_MEM_TOTAL.equals(jsonObject.getString("key_"))){
					JSONArray itemArray = new JSONArray();
					itemArray.add(jsonObject.get("itemid"));
					param.put("itemids",itemArray);
					param.put("history",3);
					JSONObject monitorJsonObject = zabbixGetMonitorData(param);
					resultObject.put("mem_total", monitorJsonObject.getJSONArray("result"));
				}
				//net
				if(jsonObject.getString("key_").startsWith(Common.HOST_NET_IN)){
					JSONArray itemArray = new JSONArray();
					itemArray.add(jsonObject.get("itemid"));
					param.put("itemids",itemArray);
					param.put("history",3);
					JSONObject monitorJsonObject = zabbixGetMonitorData(param);
					String networkName = jsonObject.getString("key_").substring(jsonObject.getString("key_").indexOf("[")+1,
							jsonObject.getString("key_").indexOf("]"));
					resultObject.put("net_in["+networkName+"]", monitorJsonObject.getJSONArray("result"));
				}
				//net
				if(jsonObject.getString("key_").startsWith(Common.HOST_NET_OUT)){
					JSONArray itemArray = new JSONArray();
					itemArray.add(jsonObject.get("itemid"));
					param.put("itemids",itemArray);
					param.put("history",3);
					JSONObject monitorJsonObject = zabbixGetMonitorData(param);
					String networkName = jsonObject.getString("key_").substring(jsonObject.getString("key_").indexOf("[")+1,
							jsonObject.getString("key_").indexOf("]"));
					resultObject.put("net_out["+networkName+"]", monitorJsonObject.getJSONArray("result"));
				}
			}else if(monitorType.endsWith("container")){
				//CPU
				if(Common.DOCKER_CPU_USED_PERSENT.equals(jsonObject.getString("key_"))){
					JSONArray itemArray = new JSONArray();
					itemArray.add(jsonObject.get("itemid"));
					param.put("itemids",itemArray);
					param.put("history",0);
					JSONObject monitorJsonObject = zabbixGetMonitorData(param);
					resultObject.put("cpu_used_persent", monitorJsonObject.getJSONArray("result"));
				}
				//mem
				if(Common.DOCKER_MEM_USED_PERSENT.equals(jsonObject.getString("key_"))){
					JSONArray itemArray = new JSONArray();
					itemArray.add(jsonObject.get("itemid"));
					param.put("itemids",itemArray);
					param.put("history",0);
					JSONObject monitorJsonObject = zabbixGetMonitorData(param);
					resultObject.put("mem_used_persent", monitorJsonObject.getJSONArray("result"));
				}
				//net
				if(jsonObject.getString("key_").startsWith(Common.DOCKER_NET_IN)){
					JSONArray itemArray = new JSONArray();
					itemArray.add(jsonObject.get("itemid"));
					param.put("itemids",itemArray);
					param.put("history",0);
					JSONObject monitorJsonObject = zabbixGetMonitorData(param);
					resultObject.put("packets_received", monitorJsonObject.getJSONArray("result"));
				}
				//net
				if(jsonObject.getString("key_").startsWith(Common.DOCKER_NET_OUT)){
					JSONArray itemArray = new JSONArray();
					itemArray.add(jsonObject.get("itemid"));
					param.put("itemids",itemArray);
					param.put("history",0);
					JSONObject monitorJsonObject = zabbixGetMonitorData(param);
					resultObject.put("packets_sent", monitorJsonObject.getJSONArray("result"));
				}
			}else{
				return new Result(false,"可监控的类型（主机：host,容器：container）传入的监控对象类型不正确：monitorType="+monitorType);
			}
			
		}
		return new Result(true,resultObject, "success");
	}
	private JSONObject zabbixAuth(JSONObject param){
		JSONObject params = new JSONObject();
		params.put("jsonrpc",ZabbixBean.jsonrpc);
		params.put("method", ZabbixBean.method_login);
		JSONObject user = new JSONObject();
		user.put("user", systemConfig.getZabbixUser());
		user.put("password", systemConfig.getZabbixPwd());
		params.put("params",user);
		params.put("id", param.get("id"));
		String api_jsonrpc = httpClient.post(params, zabbixApiUrl);
		return api_jsonrpc==null?null:JSONObject.parseObject(api_jsonrpc);
	}
	
	private JSONObject zabbixGetHost(JSONObject param){
		JSONObject hostParams = new JSONObject();
		hostParams.put("jsonrpc",ZabbixBean.jsonrpc);
		hostParams.put("method", ZabbixBean.method_get_host);
		hostParams.put("id", param.get("id"));
		hostParams.put("auth", param.get("auth"));
		JSONObject hostParamsIn = new JSONObject();
		JSONArray ja = new JSONArray();
		ja.add("hostid");
		ja.add("host");
		hostParamsIn.put("output", ja);
		JSONObject filter = new JSONObject();
		JSONArray jaserver = new JSONArray();
		jaserver.add(param.get("objectName"));
		filter.put("host",jaserver);
		hostParamsIn.put("filter", filter);
		hostParams.put("params",hostParamsIn);
		String hostString = httpClient.post(hostParams, zabbixApiUrl);
		return hostString==null?null:JSONObject.parseObject(hostString);
	}
	private JSONObject zabbixGetItem(JSONObject param){
		JSONObject itemparam = new JSONObject();
		itemparam.put("jsonrpc",ZabbixBean.jsonrpc);
		itemparam.put("method", ZabbixBean.method_get_item);
		itemparam.put("id", param.get("id"));
		itemparam.put("auth", param.get("auth"));
		JSONObject itemparamIn = new JSONObject();
		JSONArray outja = new JSONArray();
		outja.add("itemid");
		outja.add("key_");
		outja.add("name");
		itemparamIn.put("output", outja);
		itemparamIn.put("hostids",param.get("hostid") );
		itemparam.put("params",itemparamIn);
		String itemString = httpClient.post(itemparam, zabbixApiUrl);
		return itemString==null?null:JSONObject.parseObject(itemString);
	}
	
	private JSONObject zabbixGetMonitorData(JSONObject param){
		JSONObject history = new JSONObject();
		history.put("jsonrpc",ZabbixBean.jsonrpc);
		history.put("method", ZabbixBean.method_get_history);
		history.put("id", param.get("id"));
		history.put("auth", param.get("auth"));
		JSONObject historyIn = new JSONObject();
		historyIn.put("itemids",param.get("itemids") );
		historyIn.put("output", "extend");
		historyIn.put("history", param.getInteger("history"));
		historyIn.put("time_from",param.get("time_from") );
		historyIn.put("time_till",param.get("time_till") );
		historyIn.put("sortfield", "clock");
		historyIn.put("sortorder", "DESC");
		history.put("params",historyIn);
		String historyString  = httpClient.post(history, zabbixApiUrl);
		 return historyString==null?null:JSONObject.parseObject(historyString);
	}
	private void assembleUrl(){
		zabbixApiUrl = systemConfig.getZabbixServer()+"/zabbix/api_jsonrpc.php";
	}
	private Result checkParam(JSONObject paramIn){
		if(null==paramIn.get("objectName")){
			return new Result(false,"监控对象名称为空，请输入监控对象名称");
		}
		if(null==paramIn.get("time_from")){
			//默认一小时
			paramIn.put("time_from",System.currentTimeMillis()/1000-60*60);
		}
		if(null==paramIn.get("time_till")){
			paramIn.put("time_till",System.currentTimeMillis()/1000);
		}
		return new Result(true);
	}
	private JSONObject zabbixGetImmediateMonitorData(JSONObject paramIn){
		JSONObject history = new JSONObject();
		history.put("jsonrpc",ZabbixBean.jsonrpc);
		history.put("method", ZabbixBean.method_get_history);
		history.put("id", paramIn.get("id"));
		history.put("auth", paramIn.get("auth"));
		JSONObject historyIn = new JSONObject();
		historyIn.put("output", "extend");
		historyIn.put("itemids",paramIn.get("itemids"));
		historyIn.put("limit",1);
		historyIn.put("history", paramIn.getString("history"));
		historyIn.put("sortfield", "clock");
		historyIn.put("sortorder", "DESC");
		history.put("params",historyIn);
		String historyString  = httpClient.post(history, zabbixApiUrl);
		return historyString==null?null:JSONObject.parseObject(historyString);
	}
	public Result zabbixGetImmediateData(JSONObject paramIn){
		String monitorType = paramIn.getString("monitorType");
		Result result = this.checkParam(paramIn);
		if(!result.isSuccess()){
			return result;
		}
		this.assembleUrl();
		JSONObject param = new JSONObject();
		param.put("id", String.valueOf(System.currentTimeMillis()));
		JSONObject auth = this.zabbixAuth(param);
		if(null==auth){
			LOGGER.error("获取认证令牌失败");
			return new Result(false,
					"获取认证令牌失败");
		}
		param.put("auth", auth.get("result"));
		param.put("objectName",paramIn.get("objectName"));
		JSONObject monitorHost = this.zabbixGetHost(param);
		if(null==monitorHost||monitorHost.getJSONArray("result").size()==0){
			LOGGER.error("查询监控对象["+paramIn.get("objectName")+"]失败");
			return new Result(false,
					"查询监控对象["+paramIn.get("objectName")+"]失败");
		}
		param.put("hostid", monitorHost.getJSONArray("result").getJSONObject(0).get("hostid"));
		JSONObject monitorItem = this.zabbixGetItem(param);
		if(null==monitorItem){
			LOGGER.error("查询监控对象["+paramIn.get("objectName")+"]监控项["+paramIn.get("monitorItem")+"]失败");
			return new Result(false,
					"查询监控对象["+paramIn.get("objectName")+"]监控项["+paramIn.get("monitorItem")+"]失败");
		}
		JSONArray items = monitorItem.getJSONArray("result");
		JSONObject resultObject = new JSONObject();
		
		for(int i=0;i<items.size();i++){
			JSONObject jsonObject = items.getJSONObject(i);
			if(monitorType.endsWith("host")){
				//CPU
				if(Common.HOST_CPU.equals(jsonObject.getString("key_"))){
					JSONArray itemArray = new JSONArray();
					itemArray.add(jsonObject.get("itemid"));
					param.put("itemids",itemArray);
					param.put("history",0);
					JSONObject monitorJsonObject = zabbixGetImmediateMonitorData(param);
					resultObject.put("cpu", monitorJsonObject.getJSONArray("result"));
				}
				//mem
				if(Common.HOST_MEM_AVAILABLE.equals(jsonObject.getString("key_"))){
					JSONArray itemArray = new JSONArray();
					itemArray.add(jsonObject.get("itemid"));
					param.put("itemids",itemArray);
					param.put("history",3);
					JSONObject monitorJsonObject = zabbixGetImmediateMonitorData(param);
					resultObject.put("mem_available", monitorJsonObject.getJSONArray("result"));
				}
				//mem
				if(Common.HOST_MEM_TOTAL.equals(jsonObject.getString("key_"))){
					JSONArray itemArray = new JSONArray();
					itemArray.add(jsonObject.get("itemid"));
					param.put("itemids",itemArray);
					param.put("history",3);
					JSONObject monitorJsonObject = zabbixGetImmediateMonitorData(param);
					resultObject.put("mem_total", monitorJsonObject.getJSONArray("result"));
				}
				//net
				if(jsonObject.getString("key_").startsWith(Common.HOST_NET_IN)){
					JSONArray itemArray = new JSONArray();
					itemArray.add(jsonObject.get("itemid"));
					param.put("itemids",itemArray);
					param.put("history",3);
					JSONObject monitorJsonObject = zabbixGetImmediateMonitorData(param);
					String networkName = jsonObject.getString("key_").substring(jsonObject.getString("key_").indexOf("[")+1,
							jsonObject.getString("key_").indexOf("]"));
					resultObject.put("net_in["+networkName+"]", monitorJsonObject.getJSONArray("result"));
				}
				//net
				if(jsonObject.getString("key_").startsWith(Common.HOST_NET_OUT)){
					JSONArray itemArray = new JSONArray();
					itemArray.add(jsonObject.get("itemid"));
					param.put("itemids",itemArray);
					param.put("history",3);
					JSONObject monitorJsonObject = zabbixGetImmediateMonitorData(param);
					String networkName = jsonObject.getString("key_").substring(jsonObject.getString("key_").indexOf("[")+1,
							jsonObject.getString("key_").indexOf("]"));
					resultObject.put("net_out["+networkName+"]", monitorJsonObject.getJSONArray("result"));
				}
			}else if(monitorType.endsWith("container")){
				//CPU
				if(Common.DOCKER_CPU_USED_PERSENT.equals(jsonObject.getString("key_"))){
					JSONArray itemArray = new JSONArray();
					itemArray.add(jsonObject.get("itemid"));
					param.put("itemids",itemArray);
					param.put("history",0);
					JSONObject monitorJsonObject = zabbixGetImmediateMonitorData(param);
					resultObject.put("cpu_used_persent", monitorJsonObject.getJSONArray("result"));
				}
				//mem
				if(Common.DOCKER_MEM_USED_PERSENT.equals(jsonObject.getString("key_"))){
					JSONArray itemArray = new JSONArray();
					itemArray.add(jsonObject.get("itemid"));
					param.put("itemids",itemArray);
					param.put("history",0);
					JSONObject monitorJsonObject = zabbixGetImmediateMonitorData(param);
					resultObject.put("mem_used_persent", monitorJsonObject.getJSONArray("result"));
				}
				//net
				if(jsonObject.getString("key_").startsWith(Common.DOCKER_NET_IN)){
					JSONArray itemArray = new JSONArray();
					itemArray.add(jsonObject.get("itemid"));
					param.put("itemids",itemArray);
					param.put("history",0);
					JSONObject monitorJsonObject = zabbixGetImmediateMonitorData(param);
					resultObject.put("packets_received", monitorJsonObject.getJSONArray("result"));
				}
				//net
				if(jsonObject.getString("key_").startsWith(Common.DOCKER_NET_OUT)){
					JSONArray itemArray = new JSONArray();
					itemArray.add(jsonObject.get("itemid"));
					param.put("itemids",itemArray);
					param.put("history",0);
					JSONObject monitorJsonObject = zabbixGetImmediateMonitorData(param);
					resultObject.put("packets_sent", monitorJsonObject.getJSONArray("result"));
				}
			}else{
				return new Result(false,"可监控的类型（主机：host,容器：container）传入的监控对象类型不正确：monitorType="+monitorType);
			}
			
		}
		return new Result(true,resultObject, "success");
	}
}
